from matplotlib import pyplot as plt
from sklearn import tree
import pandas as pd
import numpy as np
import plotly.express as px
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
from sklearn.model_selection import train_test_split

#导入数据库

data = pd.read_csv('D:/patientdata.csv',encoding='gb18030')
#输出每一列的数据类型
print(list(data.columns))
for i in list(data.columns):
    print(data[i].dtype)

#数据描述

#求每一列的平均值
#因为最后一列不是int型，无法计算，patientdata1.csv为删除最后一列后的数据库
data1 = pd.read_csv('D:/patientdata1.csv',encoding='gb18030')
print("每列平均值为：")
print(np.average(data1,axis=0))
#求每一列的方差
#方差的意义在于，当数据越靠近方差时，获得肺癌的概率越大
print("每列方差为：")
print(np.var(data1))

#describe()函数查看数据的基本情况，包括: count 非空值数、mean 平均值、std 标准差、max 最大值、min 最小值
#set_option()函数，('display.max_columns', None)显示所有列
#set_option()函数，('display.max_rows', None)显示所有行
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
print(data.describe())
print("\n")

#数据清洗

#查看缺失数据
data.isnull().sum()
#删除有空白值的那一行
data.dropna(axis=0, how='any')
#去除数据中的空格
def delete_space(x):
    if type(x) is str:
        return x.strip()
    else:
        return x
data2 = data.applymap(delete_space)

#取行索引全部，列索引全部的数据
data2 = data2.iloc[:, :]
#查看数据的基本信息：（列排序、列索引、列非空值个数、列值类型、列值类型个数、内存占用）
data2.info()

#绘制直方图

#数据集为data2，x轴为年龄分布，以10为间隔
#Level属性有三种取值，以Level分组
fig = px.histogram(data2, x = '年龄', color = 'Level', nbins = 10, title = '年龄分布', text_auto = True)
fig.show()

#绘制箱型图

fig = px.box(data2, x = '年龄', y = 'Level')
fig.show()

#设置gragh函数，方便快速绘制直方图和箱型图

#设置x轴，y轴，表名的取值
def graph(x, y, title):
# barmode：设置条形图的形式，“group”为分组条形图
    fig = px.histogram(data2, x = x, y = y, color = 'Level', barmode = 'group',
                   title = title, text_auto = True)
    fig.show()
    fig = px.box(data2, x = x, y = 'Level')
    fig.show()

#绘制所有相关因素的直方图和箱型图

graph('Alcohol use饮酒', '性别', '饮酒程度分布（1-8）')
graph('Dust Allergy粉尘过敏', '性别', '粉尘过敏程度分布（1-8）')
graph('OccuPational Hazards职业危害', '性别', '职业危害程度分布（1-8）')
graph('Genetic Risk遗传', '性别', '遗传程度分布（1-8）')
graph('chronic Lung Disease慢性肺疾病', '性别', '慢性肺疾病程度分布（1-8）')
graph('Balanced Diet饮食均衡', '性别', '饮食均衡程度分布（1-8）')
graph('Obesity肥胖', '性别', '肥胖程度分布（1-8）')
graph('Smoking吸烟', '性别', '吸烟程度分布（1-8）')
graph('Chest Pain胸痛', '性别', '胸痛程度分布（1-8）')
graph('Coughing of Blood咳血', '性别', '咳血程度分布（1-8）')
graph('Fatigue疲劳', '性别', '疲劳程度分布（1-8）')
graph('Weight Loss体重减少', '性别', '体重减少程度分布（1-8）')
graph('Shortness of Breath呼吸衰竭', '性别', '呼吸衰竭程度分布（1-8）')
graph('Wheezing哮喘', '性别', '哮喘程度分布（1-8）')
graph('Swallowing Difficulty吞咽困难', '性别', '吞咽困难程度分布（1-8）')
graph('Frequent Cold经常感冒', '性别', '经常感冒程度分布（1-8）')
graph('Dry Cough干咳', '性别', '干咳程度分布（1-8）')
graph('Snoring打鼾', '性别', '打鼾程度分布（1-8）')

#两种性别人数在肺癌严重程度的分布
fig = px.histogram(data2, x = 'Level', y = '性别', color = '性别', barmode = 'group',
                   title = '肺癌严重程度分布', text_auto = True)
fig.show()

#利用决策树预测病患的肺癌严重程度
df = pd.read_csv('D:/patientdata2.csv',encoding='gb18030')
df = df.loc[:, ~df.columns.str.contains('^Unnamed')]
print(df.head())
#  x为可能导致糖尿病的因素
x = df.drop('Level',axis=1)
#  y为肺癌严重程度
y = df['Level']

#  将数据标准化
X = df.drop('Level',axis = 1)
#  一共1000个数据950个作为训练集，50个作为测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=50/1000)
#criterion = 'entropy'信息熵：在结果出来之前对可能产生的信息量的期望
clf = tree.DecisionTreeClassifier(criterion='gini',splitter='best', max_depth=10,
                                        min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.2)

clf.fit(X_train,y_train)
y_pred = clf.predict(X_test)
print("决策树准确率：")
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))
print(accuracy_score(y_test,y_pred))
print('模型得分: {:2f}'.format(clf.score(X_test,y_test)))
y_ = np.array(y_test)
print("决策树预测结果:",clf.predict(X_test))
print('--------------------------------------------------------------------------')
print('真实结果:         ',y_)

#病患各方面原因的数值
a = ([[3,7,8,6,5,4,3,2,1,1,3,2,4,3,1,3,4,1,2]])

#输出病患的信息
indices = [3,7,8,6,5,4,3,2,1,1,3,2,4,3,1,3,4,1,2]
l = []
for index in indices:
    l.append(index)
empty_indices = {"空气污染": l[0], "Alcohol use饮酒": l[1], "Dust Allergy粉尘过敏": l[2], "OccuPational Hazards职业危害": l[3],
                "Genetic Risk遗传": l[4], "chronic Lung Disease慢性肺疾病": l[5], "Balanced Diet饮食均衡": l[6], "Obesity肥胖": l[7],
                "Smoking吸烟": l[8], "Chest Pain胸痛": l[9], "Coughing of Blood咳血": l[10], "Fatigue疲劳": l[11],
                "Weight Loss体重减少": l[12], "Shortness of Breath呼吸衰竭": l[13], "Wheezing哮喘": l[14], "Swallowing Difficulty吞咽困难": l[15],
                "Frequent Cold经常感冒": l[16], "Dry Cough干咳": l[17], "Snoring打鼾": l[18]}
data = pd.DataFrame(empty_indices, index=[0])
data = data.set_index('空气污染')
data.to_csv("new.csv")
df_1 = pd.read_csv("new.csv")
s = df_1.iloc[0]
print("此病患的数据为：",s)

#输出预测结果
predict_result = clf.predict(a)
print("预测此病患肺癌严重程度为：",str(predict_result))

#绘制热力图
#是识别预测变量与目标变量相关性的方法，同时，也能发现变量间是否存在多重共线性

#replace()函数，将第一个参数的值替换成第二个参数的值，第三个参数代表替换次数
data2['Level'].replace(to_replace=["Low", "Medium", "High"], value = [1, 2, 3], inplace = True)

#使用StandardScaler()函数对数据集标准化，使整个数据集都以零均值和单位方差进行缩放
standard = StandardScaler()
data_standard = standard.fit_transform(data2)

#pd.DataFrame()函数，将标准化后的数据集制作成列表集
data_standard_2 = pd.DataFrame(data = data_standard, columns = data2.keys())

#corr()函数计算data_standard_2列之间的相关系数
correlation = data_standard_2.corr()

#annot:布尔值或者矩形数据，可选参数。如果为True，则在每个热力图单元格中写入数据值。
#fmt：字符串，可选参数。添加注释时要使用的字符串格式代码
graph = sns.heatmap(correlation, annot = True, fmt = '.2f')
#用matplotlib库的set_size_inches()方法图形模块设置图形尺寸(以英寸为单位)。
graph.figure.set_size_inches(24, 16)
#设置轴的标题，fontsize设置字体大小
graph.set_title('Correlation Matriz', fontsize = 30)
#展示热力图
plt.show()
